#ifndef AVALON_UIDSERVER_HPP
#define AVALON_UIDSERVER_HPP
#include "Avalon/IO/ConnectionState.hpp"
#include "Avalon/ServiceLocator/DirectoryEntry.hpp"
#include "Avalon/ServiceLocator/ServiceLocator.hpp"
#include "Avalon/ServiceLocator/ServiceLocatorServices.hpp"
#include "Avalon/Services/ServerMixin.hpp"
#include "Avalon/Services/ServiceNode.hpp"
#include "Avalon/SignalHandling/ConnectionGroup.hpp"
#include "Avalon/SignalHandling/TaskSignalHandler.hpp"
#include "Avalon/UidService/UidServices.hpp"

namespace Avalon {
namespace UidService {

  /*! \class UidServer
   *  \brief Generates unique identifiers.
   *  \author Kamal Mansouri <kranar@hotmail.com>
   */
  class UidServer : private Services::ServerMixin<UidClientChannel> {
    public:

      //! Constructs a UidServer.
      /*!
        \param serviceClient A ServiceLocatorClient connected to an Avalon
                             service network.
        \param dataStore The UidDataStore to use.
        \param connection An unused ServerConnection.
        \param dataShuttleFactory Specifies the type of serialization to use.
        \param timeout The Connection timeout.
      */
      UidServer(ServiceLocator::ServiceLocatorClient* serviceClient,
        UidDataStore* dataStore, IO::ServerConnection* connection,
        Serialization::DataShuttleFactory* dataShuttleFactory,
        boost::posix_time::time_duration timeout =
        Services::ServiceNode::TIMEOUT);

      virtual ~UidServer();

      //! Returns <code>true</code> iff the UidServer is running.
      bool IsRunning();

      //! Starts the UidServer.
      /*!
        \throw IOException if an IO operation fails.
      */
      void Start();

      //! Stops the UidServer.
      /*!
        \throw IOException if the an IO operation failed.
      */
      void Stop();

    private:
      boost::mutex m_mutex;
      ServiceLocator::ServiceLocatorClient* m_serviceClient;
      IO::ConnectionState m_serviceClientState;
      boost::scoped_ptr<UidDataStore> m_dataStore;
      IO::ConnectionState m_dataStoreState;
      boost::scoped_ptr<IO::ServerConnection> m_connection;
      IO::ConnectionState m_connectionState;
      std::vector<UidClientChannel*> m_clients;
      Services::ServiceNode m_service;
      bool m_isRunning;
      bool m_isShuttingDown;
      boost::condition_variable m_closedCondition;
      SignalHandling::TaskSignalHandler m_signalHandler;

      void Shutdown();
      void OnConnectionAccepted(
        const Threading::Async<IO::Channel*>::Ptr& result);
      void OnServiceClientClosed();
      void OnDataStoreClosed();
      void OnConnectionClosed();
      void OnClientClosed(UidClientChannel* channel);
      void OnReserveUids(
        const Services::RequestToken<ReserveUidsService>& request,
        long long blockSize);
      virtual void RemoveClient(UidClientChannel* channel);
  };
}
}

#endif // AVALON_UIDSERVER_HPP
